<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Minimalistic animation library in javascript. Fast, lightweight and easy-to-use.">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@danielundin">
    <meta name="twitter:creator" content="@danielundin">
    <meta name="twitter:title" content="snabbt.js">
    <meta name="twitter:description" content="Minimalistic animation library in javascript. Fast, lightweight and easy-to-use.">
    <meta name="twitter:image" content="http://daniel-lundin.github.io/snabbt.js/assets/snabbt-sharing.png">

    <meta property="og:url" content="http://daniel-lundin.github.io/snabbt.js">
    <meta property="og:title" content="snabbt.js" />
    <meta property="og:description" content="Minimalistic animation library in javascript. Fast, lightweight and easy-to-use." />
    <meta property="og:image" content="http://daniel-lundin.github.io/snabbt.js/assets/snabbt-sharing.png">

    <title>snabbt.js</title>
    <link href='//fonts.googleapis.com/css?family=Raleway:400,300,600' rel='stylesheet' type='text/css'>
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">

    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.2/normalize.min.css">
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.1/skeleton.min.css">

    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/solarized_dark.min.css">
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-58043335-1', 'auto');
      ga('send', 'pageview');
    </script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
    <script>hljs.initHighlightingOnLoad();</script>

    <link rel="stylesheet" href="css/custom.css">
  </head>
  <body>

    <a href="https://github.com/daniel-lundin/snabbt.js" class="hide-mobile"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://camo.githubusercontent.com/567c3a48d796e2fc06ea80409cc9dd82bf714434/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png"></a>

    <div id="docked-navbar" class="nav docked hidden hide-mobile">
      <div class="container">
        <ul>
          <li><a href="#intro">Introduction</a></li>
          <li><a href="#demos">Demos</a></li>
          <li><a href="#usage">Usage</a></li>
          <li><a href="#easing">Easing</a></li>
          <li><a href="#advanced">Advanced</a></li>
          <li><a href="#module-loaders">Module loaders</a></li>
          <li><a href="#api">API</a></li>
        </ul>
      </div>
    </div>

    <div class="container" style="margin-top: 10%">
      <div class="hero">
        <h1><span>s</span><span>n</span><span>a</span><span>b</span><span>b</span><span>t</span><span>.</span><span>j</span><span>s</span></h1>
        <p>Minimalistic animation library in javascript</p>
        <div class="row">
          <div class="four columns">
            <h3><i class="fa fa-rocket"></i>Fast</h3>
            <p>60 FPS, even on mobile</p>
          </div>
          <div class="four columns">
            <h3><i class="fa fa-paper-plane"></i>Light</h3>
            <p> ~5kb minified and gzipped</p>
          </div>
          <div class="four columns">
            <h3><i class="fa fa-user"></i>Simple</h3>
            <p>Write less, animate more</p>
          </div>
        </div>
        <p class="shell-command"><code>npm install snabbt.js</code></p>
        <p class="shell-command"><code>bower install snabbt.js</code></p>
        <a href="https://github.com/daniel-lundin/snabbt.js/releases" class="button button-primary">Download</a>
      </div>
      <div id="navbar" class="nav">
        <ul>
          <li><a href="#intro">Introduction</a></li>
          <li><a href="#demos">Demos</a></li>
          <li><a href="#usage">Usage</a></li>
          <li><a href="#easing">Easing</a></li>
          <li><a href="#advanced">Advanced</a></li>
          <li><a href="#module-loaders">Module loaders</a></li>
          <li><a href="#api">API</a></li>
        </ul>
      </div>

      <section id="intro">
        <h2>Introduction</h2>
        <p>snabbt.js is a minimalistic javascript animation library. It focuses on moving things around. It will translate, rotate, scale, skew and resize your elements. By including matrix multiplication operations, transforms can be combined in any way you want. The end result is then set via CSS3 transform matrices.</p>

        <p>snabbt.js is built to be fast. It will only animate things that modern browsers can animate <a href="http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/" target="_blank">cheaply:</a> transforms and opacity. The goal is to make a library that will let the user make smooth animations without needing to know too much about browser rendering.</p>

        <p>Note: For convenience, width and height are animatable too, but beware since they may cause page reflows and slow down your animations.</p>

        <h4>Limitations</h4>
        <ul>
          <li>All transforms work on pixels or radians. Any unit conversion has to be done beforehand.</li>
          <li>No arbitrary property animations, e.g. colors, padding, margin or line height animations.</li>
          <li>For performance reasons, snabbt never queries the DOM. This means that in some cases you need to transforms yourself.(Specifically when using value feeding)</li>
          <li>snabbt.js needs requestAnimationFrame and matrix3d to work, so no IE &lt; 10</li>
        </ul>
      </section>

      <section id="demos">
        <h2>Demos</h2>
        <p>Check out some of the demos to see the capabilities of snabbt.js:</p>
        <ul>
          <li><a href="cards.html">Cards</a></li>
          <li><a href="sticks.html">Crazy sticks</a></li>
          <li><a href="periodic.html">Periodic table</a></li>
          <li><a href="words.html">Laser words</a></li>
        </ul>
      </section>

      <section id="usage">
        <h2>Usage</h2>
        <div class="row">
          <div class="six columns">
            <p>Animations are started with the snabbt-function call. The function takes an element as first parameter(or list there of) and a configutation-object as second. Example:</p>


            <button id="usage-example-execute">Run example</button>
          </div>
          <div class="six columns">

            <pre><code class="javascript">snabbt(element, {
  position: [100, 0, 0],
  rotation: [Math.PI, 0, 0],
  easing: 'ease'
});</code></pre>
          </div>
        </div>


        <h3>Chaining</h3>
        <div class="row">
          <div class="six columns">
            <p>Animation can be chained by using `snabbt()` on the returned animation object. All fromXxx properties will be set to the end state of the previous animation.</p>
            <button id="chaining-example-execute">Run example</button>
          </div>
          <div class="six columns">
            <pre><code class="javascript">snabbt(element, {
  position: [100, 0, 0],
  easing: 'ease'
}).snabbt({
  fromRotation: [0, 0, -2*Math.PI],
  position: [0, 0, 0],
  easing: 'spring',
  springConstant: 0.2,
  springDeceleration: 0.90,
  springMass: 10,
});</code></pre>
          </div>
        </div>

        <h3>Make it stop</h3>
        <p>Animation can be stopped at any time by replacing the animation configuration with the string literal 'stop':</p>
        <pre><code class="javascript">snabbt(element, 'stop');</code></pre>
        <p class="extra-top-margin">If a new animation is started with the same element it will start from the stopped position unless the 'from'-properties are used. </p>
      </section>


      <section id="easing">
        <h2>Easing</h2>
        <p>snabbt.js includes four easing functions: linear, ease, easeIn and easeOut. You can also use your own <a href="#custom-easing">easing functions</a> or use the physics based <a href="#spring-easing">spring easing</a></p>
        <div class="row">
          <div class="six columns">
            <h5>linear(default)</h5>
            <div class="easing-demo" data-easing-name="linear">
              <div></div>
            </div>
          </div>
          <div class="six columns">
            <h5>ease</h5>
            <div class="easing-demo" data-easing-name="ease">
              <div></div>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="six columns">
            <h5>easeIn</h5>
            <div class="easing-demo" data-easing-name="easeIn">
              <div></div>
            </div>
          </div>
          <div class="six columns">
            <h5>easeOut</h5>
            <div class="easing-demo" data-easing-name="easeOut">
              <div></div>
            </div>
          </div>
        </div>

      </section>
      <section id="custom-easing">
        <h3>Custom easing function</h3>
        <div class="row">
          <div class="six columns">
            <p>Instead of easing name, pass in a function that takes one parameter:</p>
            <button id="custom-easer" class="button-primary">Run example</button>
          </div>
          <div class="six columns">
            <pre><code class="javascript">snabbt(element, {
  position: [200, 0, 0],
  easing: function(value) {
    return value + 0.3 * Math.sin(2*Math.PI * value);
  }
}).snabbt({
  position: [0, 0, 0],
  easing: 'easeOut'
});</code></pre>
          </div>
        </div>
      </section>

      <section id="spring-easing">
        <h3>Spring easing</h3>
        <p>When using spring easing, the <em>duration</em> parameter is not in effect. Instead the animation will progress until equilibrium is reached. When easing is set to <em>spring</em> there are three additional parameters that can be set on the animation configuration:</p>
        <ul>
          <li><strong>springConstant</strong> - The stiffness of the spring</li>
          <li><strong>springDeceleration</strong> - Controls how fast the velocity decreases</li>
          <li><strong>springMass</strong> - The 'weight' of the object</li>
        </ul>

        <p>Example:</p>
        <pre><code class="javascript">snabbt(element, {
  position: [100, 0, 0],
  rotation: [0, 0, 2*Math.PI],
  easing: 'spring',
  springConstant: 0.3,
  springDeceleration: 0.8,
}).snabbt({
  position: [0, 0, 0],
  easing: 'spring',
  springConstant: 0.3,
  springDeceleration: 0.8,
});</code></pre>
        <button id="spring-example" class="button-primary extra-top-margin">Run example</button>
      </section>
      <!--<section id="event-hooks">
        <h3>Life cycle events</h3>
        <p>Snabbt provides a number of events which you can to use for get information on the current state of the animation. Adding callbacks to </p>
        <ul>
          <li><strong>start</strong> - Will be called just before the animation starts.</li>
          <li><strong>update</strong> - Will be called for every update of the animation. One parameter is provided which is the current progress between 0 and 1.</li>
          <li><strong>complete</strong> - Will be called for when the animation is completed update of the animation. </li>
        </ul>
      </section>-->
      <section id="advanced">
        <h2>Advanced concepts</h2>
        <p>This section describes some of the more advanced usages.</p>

        <h3>Sequence</h3>
        <p>Chaining is convenient when animating a single element or group of elements in multiple steps. However, if you want to trigger animations on a different set of element once one animation is completed you often end up with a lot of callbacks. This is where sequencing comes into play. <em>snabbt.sequence</em> is a function call that allows you to specify an array of animations that should run in sequence.</p>
        <pre><code class="javascript">snabbt.sequence([
    [elementTwo, {
      position: [100, 0, 0],
    }],
    [elementOne, {
      position: [100, 0, 0],
    }],
    [elementOne, {
      position: [0, 0, 0],
    }],
    [elementTwo, {
      position: [0, 0, 0],
    }],
  ]
);</code></pre>
        <button id="sequence-element-example" class="button-primary extra-top-margin">Run example</button>
        <div>
          <div id="sequence-one" class="sequence-example"></div>
          <div id="sequence-two" class="sequence-example"></div>
        </div>

        <h3>Value feeding</h3>
        <p>The animation object is very simple to work with but has it limitations. Sometimes you want to do the transforms in another order. This is where value feeding comes handy. The <em>valueFeeder</em> parameter expects a function that takes two parameters, one which will progress from 0 to 1 and an identity matrix that you can modify. The function will be called every frame and should return a matrix(see <a href="#matrix">Matrix API</a>) representing the current transform.</p>
        <pre><code class="javascript">snabbt(element, {
  valueFeeder: function(i, matrix) {
    var x = Math.sin(i*Math.PI);
    return matrix.rotateZ(Math.sin(6*i*Math.PI)).translate(x*200, 0, 0);
  },
  duration: 1000
});</code></pre>
        <button id="value-feed-example" class="button-primary extra-top-margin">Run example</button>

        <h3>Transform origin</h3>
        <p>By default, rotations are applied around the center of the element. By using <em>transformOrigin</em> rotations can be performed around abritary positions.</p>
        <pre><code class="javascript">snabbt(element, {
  rotation: [0, 2*Math.PI, 0],
  transformOrigin: [element.clientWidth/2, 0, 0]
});</code></pre>
        <button id='transform-origin-example' class="button-primary extra-top-margin">Run example</button>
        <div>
          <button id='transform-origin-example-2' class="button-primary extra-top-margin">Chained example</button>
        </div>

        <h3>Manual mode</h3>
        <p>By using manual mode, animations can be fed by user input instead of just being time-based. Define your animations as you normally would but set the manual-property to true. Instead of returning a chainer object, an animation control object is returned. The control object has the following methods:</p>
        <ul>
          <li><strong>setValue(value)</strong> - value should be a number between 0 and 1 where 0 represents the beginning of the animation and 1 represents the end</li>
          <li><strong>rollback(callback)</strong> - Rollbacks the animation to the start state. The callback is an optional parameter that will be called when the rollback is completed</li>
          <li><strong>finish(callback)</strong> - Will complete the animation starting at the value last called to <em>setValue</em></li>
        </ul>
        <p>Here's silly an example of what this could be used for(powered by the great Hammer.js):</p>
        <div id="flipper-drag" class="flip-container">
          <div id="flipper-background" class="flipper-background">Peek-a-boo!</div>
          <div class="flipper" id="flipper">
            <div class="flipper-front">Drag to flip!</div>
            <div class="flipper-back">Flip me back!</div>
          </div>
        </div>

        <h3>Attention animations</h3>
        <p>snabbt.js has support for attention animations. This can be useful in form validations when you want to draw attention to a form element for example. Attention animation use spring easings.</p>
        <div class="row">
          <div class="six columns">
            <pre><code class="javascript">snabbt(element, 'attention', {
  rotation: [0, 0, Math.PI/2],
  springConstant: 1.9,
  springDeceleration: 0.9,
});</code></pre>

            <button id="attention-example-1" class="button-primary extra-top-margin">Run example</button>
          </div>
          <div class="six columns">
            <pre><code class="javascript">snabbt(element, 'attention', {
  position: [50, 0, 0],
  springConstant: 2.4,
  springDeceleration: 0.9,
});</code></pre>

            <button id="attention-example-2" class="button-primary extra-top-margin">Run example</button>
          </div>
        </div>
      </section>

      <section id="multi-element">
        <h2>Multi-element animations</h2>
        <p>Several elements can be animated with a single snabbt-call by passing a list of elements instead of just one. If you want to set different values for each of the elements you can pass initilization functions for the properties instead of actual values.</p>
        <p>The initialization functions take two parameters, the current index of the element in the collection and the total number of elements. The functions must return a value in the same format as usual, e.g. a position function initializer must return an array of three coordinates.</p>
        <p>This makes it possible to create complex animations with very little code:</p>

        <pre><code class="javascript">snabbt(document.querySelectorAll('.multi-example-box'), {
  fromRotation: [0, 0, 0],
  rotation: function(i, total) {
    return [0, 0, (i/(total - 1)) * (Math.PI/2)];
  },
  delay: function(i) {
    return i * 50;
  },
  easing: 'spring',
}).snabbt({
  rotation: [0, 0, 0],
  delay: function(i, total) {
    return (total - i - 1) * 50;
  },
  easing: 'ease',
});</code></pre>
        <button id="multi-element-example" class="button-primary extra-top-margin">Run example</button>
        <div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
          <div class="multi-example"></div>
        </div>

        <p>To see a more elaborate example of this, check out the <a href="sticks.html">sticks demo</a></p>
      </section>
      <section id="module-loaders">
        <h2>Module loaders</h2>
        <p>snabbt.js is wrapped in a UMD boilerplate which means it will work with both RequireJS and browserify.</p>
        <strong>CommonJS:</strong>
        <pre><code class="javascript">var snabbt = require('snabbt.js');

snabbt(element, {
  position: [200, 0, 0]
});
</code></pre>

        <strong>AMD:</strong>
        <pre><code class="javascript">require(['snabbt.js'], function(snabbt) {
  snabbt(element, {
    rotation: [2*Math.PI, 0, 0]
  });
});
</code></pre>
      </section>
      <section>
        <h3>jQuery</h3>
        <p>snabbt.js works with or without jQuery. If jQuery is detected snabbt will be loaded as a jQuery-plugin. When using snabbt with jQuery, the first parameter is the animation configuration:</p>
        <div class="row">
          <div class="six columns">
            <h5>With jQuery</h5>
            <pre><code class="javascript">$element.snabbt({
  position: [150, 0, 0],
  rotation: [0, 0, Math.PI],
});</code></pre>
          </div>
          <div class="six columns">
            <h5>Without jQuery</h5>
            <pre><code class="javascript">snabbt(element, {
  position: [150, 0, 0],
  rotation: [0, 0, Math.PI],
});</code></pre>
          </div>

        </div>
      </section>

      <section id="matrix">
        <h2>Matrix API</h2>
        <p>Matrix operations are performed using the Matrix class. The class has the following methods:</p>
        <ul>
          <li><strong>Matrix.translate(x, y, z)</strong> - Multiplies with a translation matrix</li>
          <li><strong>Matrix.rotateX(radians)</strong> - Multiplies with a rotation around the x-axis</li>
          <li><strong>Matrix.rotateY(radians)</strong> - Multiplies with a rotation around the y-axis</li>
          <li><strong>Matrix.rotateZ(radians)</strong> - Multiplies with a rotation around the z-axis</li>
          <li><strong>Matrix.scale(x, y)</strong> - Multiplies with a scaling matrix</li>
          <li><strong>Matrix.skew(ax, ay)</strong> - Multiplies with a skew matrix</li>
          <li><strong>Matrix.clear()</strong> - Sets the matrix to the identity matrix</li>
        </ul>
        <p>All operations are chainable to make writing matrix multiplications concise, e.g.:</p>
        <pre><code class="javascript">matrix.translate(100, 0, 0).rotateX(Math.PI);</code></pre>

        <h3 class="extra-top-margin">Freeform transforms</h3>
        <p>The matrix operations can be used outside of snabbt's animation engine. This could be useful for interactive animations. </p>
        <pre><code class="javascript">var matrix = snabbt.createMatrix();
matrix.translate(100, 0, 0);
snabbt.setElementTransform(element, matrix);</code></pre>
      </section>

      <section id="api">
        <h3>Animation configuration</h3>
        <p>The following parameters can be used in the configuration object:</p>
        <table class="hide-mobile">
          <thead>
            <tr>
              <td>Parameter</td>
              <td>Type</td>
              <td>Default</td>
              <td>Description</td>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>position</td>
              <td>Array(3)</td>
              <td>[0, 0, 0]</td>
              <td>Pixel offsets in each x-, y- and z-direction</td>
            </tr>
            <tr>
              <td>rotation</td>
              <td>Array(3)</td>
              <td>[0, 0, 0]</td>
              <td>Rotation in radians in x-, y- and z-direction</td>
            </tr>
            <tr>
              <td>scale</td>
              <td>Array(2)</td>
              <td>[1, 1]</td>
              <td>Scale in x- and y-direction</td>
            </tr>
            <tr>
              <td>rotationPost</td>
              <td>Array(3)</td>
              <td>[0, 0, 0]</td>
              <td>Rotation applied after <em>position</em> and <em>rotation</em></td>
            </tr>
            <tr>
              <td>width</td>
              <td>Scalar</td>
              <td>Unchanged</td>
              <td>Element width in pixels(<em>fromWidth</em> mandatory if used)</td>
            </tr>
            <tr>
              <td>height</td>
              <td>Scalar</td>
              <td>Unchanged</td>
              <td>Element height in pixels(<em>fromHeight</em> mandatory if used)</td>
            </tr>
            <tr>
              <td>opacity</td>
              <td>Scalar</td>
              <td>1</td>
              <td>Element opacity(0 - 1)(<em>fromOpacity</em> mandatory if used)</td>
            </tr>
            <tr>
              <td>duration</td>
              <td>Scalar</td>
              <td>500</td>
              <td>Animation duration in milliseconds</td>
            </tr>
            <tr>
              <td>delay</td>
              <td>Scalar</td>
              <td>0</td>
              <td>Delay before the animation is started in milliseconds</td>
            </tr>
            <tr>
              <td>start(index, total)</td>
              <td>function</td>
              <td>undefined</td>
              <td>Function to be called just before the animation starts. If multiple elements are animated, this function will be called once for every element with two parameters, index of current element and total elements in the animated collection.</td>
            </tr>
            <tr>
              <td>update(i, index, total)</td>
              <td>function</td>
              <td>undefined</td>
              <td>Function to be called on every progress step of the animation. The first parameter is a value between 0 and 1 and indicates the current progress of the animation. If multiple elements are animated, this function will be called for every progress step for every element in the collection. <em>index</em> indicates the current element and <em>total</em> corresponds to the total number of elements in the colletion.</td>
            </tr>
            <tr>
              <td>complete(index, total)</td>
              <td>function</td>
              <td>undefined</td>
              <td>Function to be called when animation is completed. If multiple elements are animated, this function will be called once for every element with two parameters, index of current element and total elements in the animated collection. <em>this</em> will be bound the current element</td>
            </tr>
            <tr>
              <td>allDone</td>
              <td>function</td>
              <td>undefined</td>
              <td>Will be called once independent of how many elements animated</td>
            </tr>
          </tbody>
        </table>
        <ul class="hide-desktop">
          <li><strong>position</strong> - Pixel offsets in each x-, y- and z-direction</li>
          <li><strong>rotation</strong> - Rotation in radians in x-, y- and z-direction</li>
          <li><strong>scale</strong> - Scale in x- and y-direction</li>
          <li><strong>rotationPost</strong> - Rotation applied after <em>position</em> and <em>rotation</em></li>
          <li><strong>width</strong> - Element width in pixels(<em>fromWidth</em> mandatory if used)</li>
          <li><strong>height</strong> - Element height in pixels(<em>fromHeight</em> mandatory if used)</li>
          <li><strong>opacity</strong> - Element opacity(0 - 1)(<em>fromOpactiy</em> mandatory if used)</li>
          <li><strong>duration</strong> - Animation duration in milliseconds</li>
          <li><strong>delay</strong> - Delay before the animation is started in milliseconds</li>
          <li><strong>complete(index, total)</strong> - Function to be called when animation is completed. If multiple elements are animated, this function will be called once for every element with two parameters, index of current element and total elements in the animated collection. <em>this</em> will be bound the current element</li>
          <li><strong>allDone</strong> - Will be called once independent of how many elements animated</li>
        </ul>

        <p>A 'from'-property can be set on most properties. Note that 'from' has precedance over the previous end state.</p>
        <table class="hide-mobile">
          <thead>
            <tr>
              <td>Parameter</td>
              <td>Type</td>
              <td>Default</td>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>fromPosition</td>
              <td>Array(3)</td>
              <td>[0, 0, 0] or previous end state</td>
            </tr>
            <tr>
              <td>fromRotation</td>
              <td>Array(3)</td>
              <td>[0, 0, 0] or previous end state</td>
            </tr>
            <tr>
              <td>fromScale</td>
              <td>Array(2)</td>
              <td>[1, 1] or previous end state</td>
            </tr>
            <tr>
              <td>fromRotationPost</td>
              <td>Array(3)</td>
              <td>[0, 0, 0] or previous end state</td>
            </tr>
            <tr>
              <td>fromWidth</td>
              <td>Scalar</td>
              <td>Previous end state width</td>
            </tr>
            <tr>
              <td>fromHeight</td>
              <td>Scalar</td>
              <td>Previous end state height</td>
            </tr>
            <tr>
              <td>fromOpacity</td>
              <td>Scalar</td>
              <td>Previous end state opacity</td>
            </tr>
          </tbody>
        </table>

        <ul class="hide-desktop">
          <li><strong>fromPosition</strong> - set to [0, 0, 0] or previous end state</li>
          <li><strong>fromScale</strong> - set to [0, 0, 0] or previous end state</li>
          <li><strong>fromWidth</strong> - Mandatory if <em>width</em> is used</li>
          <li><strong>fromHeight</strong> - Mandatory if <em>height</em> is used</li>
          <li><strong>fromOpacity</strong> - Mandatory if <em>opacity</em> is used</li>
        </ul>
      </section>
    </div>
    <footer>
      <div class="container">
        <p>&copy; <a href="https://twitter.com/danielundin">Daniel Lundin</a> 2015 <a href="https://github.com/daniel-lundin/snabbt.js">Source</a></p>
      </div>
    </footer>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript" src="//hammerjs.github.io/dist/hammer.min.js"></script>
    <script src="snabbt.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.3/fastclick.min.js"></script>
    <script src="docs.js"></script>
  </body>
</html>
